package com.sujeet.learning.caching;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class DataSource {
	
	private DataSource() {};
	LruCache<Integer, String> cache = new LruCache<Integer, String>();
	
	private static class SingletonHolder {
		public static final DataSource INSTANCE = new DataSource();
	}
	
	public static DataSource getInstance() {
		return SingletonHolder.INSTANCE;
	}
	
	public String get(Integer key) {
		String ret;
		Long time = System.currentTimeMillis();
		System.out.println("Thread: "+ Thread.currentThread().getId() + " " + System.currentTimeMillis() + " : get start");
		if (cache.contains(key)) {
			ret = cache.get(key);
			System.out.println("Thread: "+ Thread.currentThread().getId() + " get from Cache ends in "+ (System.currentTimeMillis() - time) + " ms");
		} else {
			String val = null;
			try {
				val = getFromFile(key);
			} catch (Exception e) {
				e.printStackTrace();
			}
			cache.update(key, val);
			ret =  val;
			System.out.println("Thread: "+ Thread.currentThread().getId() + " get from real source ends in " + (System.currentTimeMillis() - time) + " ms");
		}		
		return ret;
	}
	
	public String getFromFile(Integer key) throws IOException{
		String ret = null;
		//later implement io from file
		File file = new File("/opt/downloads/Data.txt");
		FileInputStream fis = null;
		BufferedReader br = null;
		try {
			fis = new FileInputStream(file);
			br = new BufferedReader(new InputStreamReader(fis));
			String line = null;
			while ((line = br.readLine()) != null) {
				String[] parts = line.split(":");
				String name = parts[0];
				String value = parts[1];
				if (Integer.toString(key).equals(name)) {
					ret = value;
					return ret;
				}				
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (br != null) br.close();
			if (fis != null) fis.close();
		}
		return  ret;
	}
	
	public Long showHits() {
		return cache.getHits();
	}
	
	public String cacheState() {
		return cache.toString();
	}
	
	public Long showMisses() {
		return cache.getMisses();
	}
}
